package com.wobito.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wobito.common.constants.BusinessException;
import com.wobito.common.constants.ErrorCode;
import com.wobito.common.constants.SysConstants;
import com.wobito.common.utils.DateUtils;
import com.wobito.common.utils.StringUtils;
import com.wobito.mapper.CabinetMapper;
import com.wobito.pojo.bean.Cabinet;
import com.wobito.pojo.dto.api.GetAllCabinetDTO;
import com.wobito.pojo.dto.api.LatByAllCabinetDTO;
import com.wobito.pojo.dto.cabinet.AllCabinetDTO;
import com.wobito.pojo.dto.cabinet.CabinetBriefDTO;
import com.wobito.pojo.dto.cabinet.CabinetDTO;
import com.wobito.pojo.enums.IsDeletedEnum;
import com.wobito.pojo.vo.cabinet.AddCabinetVO;
import com.wobito.pojo.vo.cabinet.CabinetVO;
import com.wobito.pojo.vo.cabinet.UpdateCabinetVO;
import com.wobito.service.ICabinetService;
import com.wobito.system.socket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * <p>
 * 柜子表 服务实现类
 * </p>
 *
 * @author lambyang
 * @since 2024-08-26
 */
@Service
public class CabinetServiceImpl extends ServiceImpl<CabinetMapper, Cabinet> implements ICabinetService {

    @Autowired
    private CabinetMapper cabinetMapper;
    @Autowired
    private WebSocketServer webSocketServer;

    @Override
    public List<CabinetDTO> selectCabinetList(CabinetVO cabinetVO) {
        return cabinetMapper.selectCabinetList(cabinetVO);
    }

    @Override
    public List<CabinetBriefDTO> selectBrief(Long areaId) {
        List<CabinetBriefDTO> cabinetBriefDTOS = new ArrayList<>();
        List<Cabinet> cabinets = cabinetMapper.selectList(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getAreaId, areaId).eq(Cabinet::getIsDeleted, IsDeletedEnum.NORMAL.getCode()));
        if (CollectionUtil.isNotEmpty(cabinets)) {
            cabinetBriefDTOS = cabinets.stream().map(c -> {
                CabinetBriefDTO cabinetBriefDTO = BeanUtil.copyProperties(c, CabinetBriefDTO.class);
                return cabinetBriefDTO;
            }).collect(Collectors.toList());
        }
        return cabinetBriefDTOS;
    }

    @Override
    public List<GetAllCabinetDTO> selectAllCabinet() {
        List<GetAllCabinetDTO> getAllCabinetDTOS = new ArrayList<>();
        List<AllCabinetDTO> allCabinetDTOS = cabinetMapper.selectAllCabinet();
        Map<String, List<AllCabinetDTO>> cabinetMap = allCabinetDTOS.stream().collect(Collectors.groupingBy(AllCabinetDTO::getSequenceCode));
        if (CollectionUtil.isNotEmpty(cabinetMap)) {
            for (Map.Entry<String, List<AllCabinetDTO>> entry : cabinetMap.entrySet()) {
                String key = entry.getKey();
                List<AllCabinetDTO> value = entry.getValue();
                GetAllCabinetDTO getAllCabinetDTO = new GetAllCabinetDTO();
                getAllCabinetDTO.setSequenceCode(key);
                getAllCabinetDTO.setCabinetName(value.get(0).getCabinetName());
                getAllCabinetDTO.setAreaName(value.get(0).getAreaName());
                getAllCabinetDTO.setStatus(value.get(0).getIsDeleted() == 0 ? "正常" : "停用");
                List<LatByAllCabinetDTO> lats = new ArrayList<>();
                for (AllCabinetDTO cabinetLat : value) {
                    if (StringUtils.isNotEmpty(cabinetLat.getLatName()) || cabinetLat.getState() != null) {
                        LatByAllCabinetDTO lat = new LatByAllCabinetDTO();
                        lat.setLatName(cabinetLat.getLatName());
                        lat.setState(cabinetLat.getState() == 0 ? "正常" : "停用");
                        lats.add(lat);
                    }
                }
                getAllCabinetDTO.setCabinetLats(lats);
                getAllCabinetDTOS.add(getAllCabinetDTO);
            }
        }
        return getAllCabinetDTOS;
    }

    @Override
    public List<String> selectCabinetCodeList() {
        return cabinetMapper.selectCabinetCodeList();
    }

    @Override
    public Cabinet selectCabinetByCode(String sequenceCode) {
        Cabinet cabinet = cabinetMapper.selectOne(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getSequenceCode, sequenceCode));
        return cabinet;
    }

    @Override
    public String selectCabinetIsOnlineByCode(Long cabinetId) {
        Cabinet cabinet = cabinetMapper.selectById(cabinetId);
        if (ObjectUtil.isNull(cabinet)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "柜子不存在");
        }
        boolean isOnline = false;
        try {
            CompletableFuture<Boolean> isOnlineFuture = webSocketServer.checkEquipmentOnline(cabinet.getSequenceCode(), SysConstants.CHECK_CABINET_STATE);
            isOnline = isOnlineFuture.get();
        } catch (InterruptedException e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "websocket请求异常");
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
        if (!cabinet.getIsOnline().equals(isOnline ? SysConstants.STATE_FILE_ZK : SysConstants.STATE_SYSTEM_TY)) {
            cabinet.setIsOnline(isOnline ? SysConstants.STATE_FILE_ZK : SysConstants.STATE_SYSTEM_TY);
            cabinetMapper.updateById(cabinet);
        }
        return isOnline ? "设备在线" : "设备离线或未回复";
    }

    @Override
    public String selectCabinetIsOnlineByCode(String sequenceCode) {
        Cabinet cabinet = cabinetMapper.selectOne(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getSequenceCode, sequenceCode));
        if (ObjectUtil.isNull(cabinet)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "柜子不存在");
        }
        boolean isOnline = false;
        try {
            CompletableFuture<Boolean> isOnlineFuture = webSocketServer.checkEquipmentOnline(sequenceCode, SysConstants.CHECK_CABINET_STATE);
            isOnline = isOnlineFuture.get();
        } catch (InterruptedException e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "websocket请求异常");
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
        if (!cabinet.getIsOnline().equals(isOnline ? SysConstants.STATE_FILE_ZK : SysConstants.STATE_SYSTEM_TY)) {
            cabinet.setIsOnline(isOnline ? SysConstants.STATE_FILE_ZK : SysConstants.STATE_SYSTEM_TY);
            cabinetMapper.updateById(cabinet);
        }
        return isOnline ? "设备在线" : "设备离线或未回复";
    }

    @Override
    public int insertCabinet(AddCabinetVO addCabinetVO) {
        Cabinet cabinet = BeanUtil.copyProperties(addCabinetVO, Cabinet.class);
        return cabinetMapper.insert(cabinet);
    }

    @Override
    public int updateCabinet(UpdateCabinetVO updateCabinetVO) {
        Cabinet cabinet = BeanUtil.copyProperties(updateCabinetVO, Cabinet.class);
        cabinet.setUpdateTime(DateUtils.getNowDate());
        return cabinetMapper.updateById(cabinet);
    }
}
